home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
util
/
dres.1
< prev
next >
Wrap
Text File
|
1988-10-25
|
52KB
|
2,217 lines
Path: xanth!nic.MR.NET!umn-d-ub!rutgers!mailrus!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i016: dres - an object-oriented resource library, Part01/03
Message-ID: <9821@swan.ulowell.edu>
Date: 25 Oct 88 00:53:31 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2206
Approved: page@swan.ulowell.edu
Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 16
Archive-name: util/dres.1
# This is a shell archive. Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
# src/ipc.c
# src/misc.c
# src/newres.c
# src/mem.asm
# util/gtd.c
# util/testipc.c
# util/test.c
# util/qtest.c
# util/testarg.c
# util/x.c
#
if `test ! -d src`
then
mkdir src
echo "mkdir src"
fi
if `test ! -s src/ipc.c`
then
echo "writing src/ipc.c"
cat > src/ipc.c << '\Rogue\Monster\'
/*
* IPC.C 25 September 1988
*
* NOTE! the BSS segment is not initialized to 0.
*/
#include <local/typedefs.h>
#include <local/ipc.h>
extern EXECBASE *SysBase;
static long IPCLock[2] = { 0, 0 };
static MLIST IPCList = { (MNODE *)&IPCList.mlh_Tail, NULL, (MNODE *)&IPCList.mlh_Head };
extern void *FindName();
extern IPCMSG *lSendIPC2();
extern char *CCall();
extern APTR Duplicate();
/*
* Three-pass command parser.
* (1) Determine # of arguments and allocate argv array, resolve variables
* (2) Determine length of each argument and allocate entries in the array
* (3) Fill entries in the array
*
* On return, an filled ARGV array will be returned. To free the argv
* array and elements, call FreeParseCmd(argv). Individual argv[]
* entries may be modified, including stuffing different pointers in,
* without effecting FreeParseCmd(). Note that offset -1 in each entry
* contains a status byte, currently only bit 0 (was quoted) is used.
*/
lParseCmd(buf, pav, varget, varfree, error, reserved)
char *buf;
char ***pav;
char *((*varget)());
char *((*varfree)());
long *error;
{
short numac; /* # of argv entries */
char **av = NULL; /* argv array */
long *arglen = NULL; /* array of entry lengths */
MLIST VList; /* Hold $variable contents */
char *endstrvar(); /* extracts variable name */
short ttllen = 0; /* sum of lengths of entries */
NewList(&VList);
*error = 0;
/*
* PASS1, determine # of arguments and retrieve variables
*/
{
register char *ptr;
register short ac = 0;
register short quo = 0;
for (ptr = buf; *ptr == ' ' || *ptr == 9; ++ptr);
for (; *ptr; ++ptr) {
switch(*ptr) {
case '(':
++quo;
break;
case ')':
--quo;
break;
case '\\':
case '^':
if (ptr[1])
++ptr;
break;
case ' ':
case 9:
if (!quo) {
while (*ptr == ' ' || *ptr == 9)
++ptr;
if (*ptr)
++ac;
--ptr;
}
break;
case '$':
{
short len;
char tmp[64];
char *str;
MNODE *vl;
++ptr;
str = endstrvar(ptr, &len);
if (*ptr == '(')
++ptr;
BMov(ptr, tmp, len);
tmp[len] = 0;
if (varget && (ptr = (char *)CCall(varget, tmp))) {
vl = AllocMem(8 + strlen(ptr) + 1, MEMF_PUBLIC);
if (!vl) {
*error = (PERR_NOMEM << 16) | (ptr - buf);
goto fail;
}
strcpy(vl+1, ptr);
if (varfree)
CCall(varfree, ptr);
} else {
*error = (PERR_NOVAR << 16) | (ptr - buf);
goto fail;
}
AddTail(&VList, vl);
ptr = str - 1;
}
break;
}
}
++ac;
numac = ac;
}
/*
* av[-1] = master string pointer (see below)
* av[-2] = sizeof av array
* av[ac] = NULL
*
* Pass 2, allocate argv array and storage for the lengths of each
* entry. Determine the length of each entry.
*/
av = AllocMem(sizeof(char *) * (numac + 3), MEMF_PUBLIC);
if (!av) {
*error = (PERR_NOMEM << 16);
goto fail;
}
av += 2;
av[-2] = (char *)(sizeof(char *) * (numac + 3));
arglen = AllocMem(sizeof(long) * numac, MEMF_PUBLIC);
if (!arglen) {
*error = (PERR_NOMEM << 16);
goto fail;
}
{
register char *ptr;
register short ac = 0;
register short quo = 0;
register short len = 0;
for (ptr = buf; *ptr == ' ' || *ptr == 9; ++ptr);
for (; *ptr; ++ptr) {
switch(*ptr) {
case '(':
++quo;
if (quo != 1)
++len;
break;
case ')':
--quo;
if (quo)
++len;
break;
case '\\':
case '^':
if (ptr[1]) {
++ptr;
++len;
}
break;
case ' ':
case 9:
if (!quo) {
while (*ptr == ' ' || *ptr == 9)
++ptr;
if (*ptr) {
arglen[ac] = len;
ttllen += len + 2;
++ac;
len = 0;
}
--ptr;
} else {
++len;
}
break;
case '$':
{
register MNODE *node = RemHead(&VList);
if (node) {
len += strlen(node+1);
AddTail(&VList, node);
}
ptr = endstrvar(ptr + 1, NULL) - 1;
}
break;
case '\n':
break;
default:
++len;
break;
}
}
arglen[ac] = len;
ttllen += len + 2; /* 1 byte status & 1 byte separator */
++ac;
}
{ /* allocate space for entries */
register short i;
register char *mem = AllocMem(4+ttllen, MEMF_PUBLIC);
register char *ptr = mem + 4;
if (!mem) {
*error = (PERR_NOMEM << 16);
goto fail;
}
*(long *)mem = 4 + ttllen;
for (i = 0; i < numac; ++i) {
*ptr++ = 0; /* status byte */
av[i] = ptr;
ptr[arglen[i]] = 0;
ptr += arglen[i] + 1;
}
av[-1] = mem;
}
{
register char *ptr;
register char *avs = av[0];
register short ac = 0;
short quo = 0;
for (ptr = buf; *ptr == ' ' || *ptr == 9; ++ptr);
for (; *ptr; ++ptr) {
switch(*ptr) {
case '\\':
if (ptr[1])
*avs++ = *++ptr;
break;
case '^':
if (ptr[1])
*avs++ = *++ptr & 0x1F;
break;
case '(':
++quo;
if (quo != 1)
*avs++ = '(';
else if (avs == av[ac]) /* quoted argument */
avs[-1] = 1;
break;
case ')':
--quo;
if (quo) {
*avs++ = ')';
break;
} /* fall through */
case ' ':
case 9:
if (!quo) {
++ptr;
while (*ptr == ' ' || *ptr == 9)
++ptr;
if (*ptr) {
*avs = 0;
avs = av[++ac];
}
--ptr;
} else {
*avs++ = *ptr;
}
break;
case '$':
{
register MNODE *node = RemHead(&VList);
if (node) {
strcpy(avs, node + 1);
avs += strlen(avs);
FreeMem(node, 8 + strlen(node+1) + 1);
}
ptr = endstrvar(ptr + 1, NULL) - 1;
}
break;
case '\n':
break;
default:
*avs++ = *ptr;
break;
}
}
*avs = 0;
++ac;
}
FreeMem(arglen, sizeof(long) * numac);
*pav = av;
av[numac] = NULL;
return(numac);
fail:
{
register MNODE *node;
if (arglen)
FreeMem(arglen, sizeof(long) * numac);
if (av)
FreeMem(av - 2, (long)av[-2]);
while (node = RemHead(&VList))
FreeMem(node, 8 + strlen(node+1) + 1);
}
*pav = NULL;
return(0);
}
lFreeParseCmd(av)
char **av;
{
FreeMem(av[-1], *(long *)av[-1]);
FreeMem(av - 2, (long)av[-2]);
}
char *
endstrvar(ptr, plen)
short *plen;
register char *ptr;
{
register short len = 0;
if (*ptr == '(') {
++ptr;
while (*ptr && *ptr != ')') {
++ptr;
++len;
}
if (*ptr == ')')
++ptr;
} else {
while ((*ptr >= 'a' && *ptr <= 'z') ||
(*ptr >= 'A' && *ptr <= 'Z') ||
(*ptr >= '0' && *ptr <= '9') ||
(*ptr == '_')) {
++len;
++ptr;
}
}
if (len > 62)
len = 62;
if (plen)
*plen = len;
return(ptr);
}
IPCPORT *
lOpenIPC(name, flags)
char *name;
{
register IPCPORT *port;
register char *ptr;
port = AllocMem(sizeof(IPCPORT), MEMF_PUBLIC|MEMF_CLEAR);
if (!port)
goto fail;
ptr = AllocMem(strlen(name)+1, MEMF_PUBLIC);
if (!ptr)
goto fail;
strcpy(ptr, name);
port->Flags = flags;
port->Port.mp_Node.ln_Type = NT_MSGPORT;
port->Port.mp_Node.ln_Name = ptr;
port->Port.mp_Flags = PA_SIGNAL;
port->Port.mp_SigBit = AllocSignal(-1);
port->Port.mp_SigTask = FindTask(NULL);
NewList(&port->Port.mp_MsgList);
LockAddr(IPCLock);
Insert(&IPCList, port, FindName(&IPCList, name));
UnLockAddr(IPCLock);
return(port);
fail:
if (port) {
FreeMem(port, sizeof(IPCPORT));
if (ptr)
FreeMem(ptr, strlen(ptr)+1);
}
return(NULL);
}
void
lCloseIPC(port)
register IPCPORT *port;
{
register IPCMSG *msg;
LockAddr(IPCLock); /* remove port (no new messages) */
Remove(port);
UnLockAddr(IPCLock);
while (msg = GetMsg(port)) /* reply to pending msgs w/error */
ReplyIPC(msg, NULL, 0, IF_NOTFND);
FreeMem(port->Port.mp_Node.ln_Name, strlen(port->Port.mp_Node.ln_Name)+1);
if (port->Port.mp_Flags == PA_SIGNAL)
FreeSignal(port->Port.mp_SigBit);
FreeMem(port, sizeof(IPCPORT));
}
/*
* msg = SendIPC(appname, buf, len, flags)
*/
IPCMSG *
lSendIPC(name, buf, len, flags)
char *name;
APTR buf;
register long len, flags;
{
register IPCMSG *msg;
register PORT *rport;
msg = AllocMem(sizeof(IPCMSG)+sizeof(PORT), MEMF_PUBLIC|MEMF_CLEAR);
if (msg == NULL)
return(NULL);
flags |= IF_ALLOCMSG; /* auto-deallocate later on */
rport = (PORT *)(msg + 1);
if (buf && !(flags & IF_NOCOPY) && !(flags & IF_ALLOC)) {
if (!(buf = Duplicate(buf, len))) {
FreeMem(msg, sizeof(IPCMSG)+sizeof(PORT));
return(NULL);
}
flags |= IF_ALLOC;
}
rport->mp_Node.ln_Type = NT_MSGPORT;
rport->mp_Flags = PA_SIGNAL;
rport->mp_SigBit = 4;
rport->mp_SigTask = SysBase->ThisTask;
NewList(&rport->mp_MsgList);
msg->Msg.mn_ReplyPort = rport;
msg->Msg.mn_Length = sizeof(IPCMSG) + sizeof(PORT);
msg->TBuf = buf;
msg->TLen = len;
msg->TFlags = flags;
return(lSendIPC2(name, msg));
}
IPCMSG *
lSendIPC2(name, msg)
char *name;
register IPCMSG *msg;
{
register IPCPORT *port;
msg->RBuf = NULL;
msg->RLen = 0;
msg->RFlags = 0;
msg->Error = 0;
msg->Confirm = NULL;
LockAddr(IPCLock);
if (name) {
port = (IPCPORT *)FindName(&IPCList, name);
} else {
port = GetHead(&IPCList);
}
msg->ToPort = port;
if (port) {
if ((port->Flags & IF_ALLOC) && !(msg->TFlags & IF_ALLOC)) {
if ((msg->TBuf = Duplicate(msg->TBuf, msg->TLen)) == NULL) {
msg->Error = PERR_NOMEM;
lReplyIPC(msg, NULL, 0, IF_ERROR);
return(msg);
}
msg->TFlags |= IF_ALLOC;
}
PutMsg(port, msg);
UnLockAddr(IPCLock);
} else {
UnLockAddr(IPCLock);
lReplyIPC(msg, NULL, 0, IF_ERROR|IF_NOTFND|IF_NOAPP);
}
return(msg);
}
/*
* DoIPC2(name, msg, collfunc, collport)
*
* Synchronous IPC routine. To prevent lockouts in case the calling task
* also owns an IPC port, if this port is provided 'collfunc' will
* automatically be called if new requests arrive while we are waiting
* for our request to complete. This call is reentrant.
*/
void
lDoIPC2(name, msg, func, port)
char *name;
IPCMSG *msg;
void (*func)();
PORT *port;
{
SendIPC2(name, msg); /* send the message */
if (port) {
register long mask1 = 1 << port->mp_SigBit;
register long mask2 = 1 << msg->Msg.mn_ReplyPort->mp_SigBit;
while (!CheckMsg(msg)) {
if (CheckPort(port)) {
CCall(func, port);
continue;
}
Wait(mask1 | mask2);
}
}
WaitMsg(msg);
}
/*
* (void )ReplyIPC(msg, buf, len, flags)
*/
lReplyIPC(msg, buf, len, flags)
register IPCMSG *msg;
APTR buf;
long len, flags;
{
if (buf && !(flags & (IF_NOCOPY|IF_ALLOC|IF_NOTFND))) {
buf = Duplicate(buf, len);
flags |= IF_ALLOC;
}
if (buf || !(flags & IF_NOTFND)) {
if ((msg->RFlags & IF_ALLOC) && msg->RBuf && buf != msg->RBuf)
FreeMem(msg->RBuf, msg->RLen);
msg->RBuf = buf;
msg->RLen = len;
}
msg->RFlags = flags;
LockAddr(IPCLock);
if (msg->RFlags & IF_GLOBAL) {
register IPCPORT *next;
do {
next = GetSucc(next);
} while (next && !(next->Flags & IF_GLOBAL));
if (next) {
msg->ToPort = next;
PutMsg(next, msg);
} else {
if ((msg->TFlags & IF_ALLOC) && msg->TBuf) {
FreeMem(msg->TBuf, msg->TLen);
msg->TBuf = NULL;
}
ReplyMsg(msg);
}
UnLockAddr(IPCLock);
return;
}
if (flags & IF_NOTFND) {
register IPCPORT *next = GetSucc(msg->ToPort);
if (next && strcmp(msg->ToPort->Port.mp_Node.ln_Name, next->Port.mp_Node.ln_Name) == 0) {
msg->ToPort = next;
PutMsg(next, msg);
} else {
if ((msg->TFlags & IF_ALLOC) && msg->TBuf) {
FreeMem(msg->TBuf, msg->TLen);
msg->TBuf = NULL;
}
ReplyMsg(msg);
msg->RFlags |= IF_ERROR;
}
UnLockAddr(IPCLock);
return;
}
UnLockAddr(IPCLock);
if ((msg->TFlags & IF_ALLOC) && msg->TBuf) {
FreeMem(msg->TBuf, msg->TLen);
msg->TBuf = NULL;
}
ReplyMsg(msg);
return;
}
/*
* (void) lFreeIPC(msg)
*
* Free space associated with the reply buffer and possibly the message
* itself. This call MUST be made after you receive a reply to your
* message.
*/
void
lFreeIPC(msg)
register IPCMSG *msg;
{
if ((msg->RFlags & IF_ALLOC) && msg->RBuf) {
FreeMem(msg->RBuf, msg->RLen);
msg->RBuf = NULL;
}
if (msg->Confirm) /* Confirmation requested */
CCall(msg->Confirm, msg);
if (msg->TFlags & IF_ALLOCMSG) /* Message was allocated */
FreeMem(msg, msg->Msg.mn_Length);
}
APTR
Duplicate(buf, len)
APTR buf;
long len;
{
APTR newbuf;
if (newbuf = AllocMem(len, TypeOfMem(buf))) {
BMov(buf, newbuf, len);
return(newbuf);
}
return(NULL);
}
#asm
; CCall(funcptr, argument)
_CCall: movem.l 4(sp),A0/A1
movem.l D2/D3/A4/A5/A6,-(sp)
move.l A1,-(sp)
jsr (A0)
addq.l #4,sp
movem.l (sp)+,D2/D3/A4/A5/A6
rts
#endasm
\Rogue\Monster\
else
echo "will not over write src/ipc.c"
fi
if [ `wc -c src/ipc.c | awk '{printf $1}'` -ne 12876 ]
then
echo `wc -c src/ipc.c | awk '{print "Got " $1 ", Expected " 12876}'`
fi
if `test ! -s src/misc.c`
then
echo "writing src/misc.c"
cat > src/misc.c << '\Rogue\Monster\'
/*
* MISC.C
*
* General Stuff... mostly in assembly.
*/
#include <local/typedefs.h>
typedef struct {
NODE ml_Node;
uword ml_NumEntries;
MEMENTRY ml_ME[2];
} MYMEMLIST;
APTR
lGetTaskData(name, bytes)
char *name;
long bytes;
{
extern EXECBASE *SysBase;
extern void *FindName2();
register LIST *list;
register MEMLIST *ml;
list = &SysBase->ThisTask->tc_MemEntry;
if (ml = FindName2(list, name))
return(ml->ml_ME[0].me_Un.meu_Addr);
if (!list->lh_Head)
NewList(list);
{
MYMEMLIST Ml;
Ml.ml_NumEntries = 2;
Ml.ml_ME[0].me_Un.meu_Reqs = MEMF_PUBLIC|MEMF_CLEAR;
Ml.ml_ME[0].me_Length = bytes;
Ml.ml_ME[1].me_Un.meu_Reqs = MEMF_PUBLIC;
Ml.ml_ME[1].me_Length = strlen(name)+1;
if (ml = AllocEntry(&Ml)) {
ml->ml_Node.ln_Name = (char *)ml->ml_ME[1].me_Un.meu_Addr;
strcpy(ml->ml_Node.ln_Name, name);
AddHead(list, ml);
return(ml->ml_ME[0].me_Un.meu_Addr);
}
}
return(NULL);
}
lFreeTaskData(name)
char *name;
{
extern EXECBASE *SysBase;
extern void *FindName2();
register MEMLIST *ml;
if (ml = FindName2(&SysBase->ThisTask->tc_MemEntry, name)) {
Remove(ml);
FreeEntry(ml);
return(1);
}
return(0);
}
#asm
include "exec/types.i"
include "exec/ports.i"
include "exec/tasks.i"
include "exec/execbase.i"
include "exec/ables.i"
include "exec/memory.i"
; NOTE: LockAddr/UnLockAddr referenced elsewhere in
; this library
; MISC.ASM
public _lWildCmp ; Wildcard compare
public _lWaitMsg ; Wait for a message to be replied
public _lCheckMsg ; Check if message has been returned
public _lCheckPort ; Check if message pending on port
public _lDoSyncMsg ; Put and Wait for a message
public _lLockAddr
public _lLockAddrB
public _lUnLockAddr
public _lUnLockAddrB
public _lFindName2
public _LVOWait
public _LVORemove
public _LVODisable
public _LVOEnable
public _LVOFindTask
public _LVOSignal
public _LVOForbid
public _LVOPermit
public _LVOPutMsg
_lDoSyncMsg: movem.l A2/A3/A6,-(sp) ; A0=port, A1=msg
move.l 4,A6 ; A6=execbase
sub.w #MP_SIZE,sp ; initialize reply port
move.b #NT_MSGPORT,LN_TYPE(sp)
move.b #PA_SIGNAL,MP_FLAGS(sp)
move.b #4,MP_SIGBIT(sp) ; EXEC semaphore signal
move.l ThisTask(A6),MP_SIGTASK(sp)
lea MP_MSGLIST(sp),A2
lea MP_MSGLIST+4(sp),A3
move.l A3,(A2) ; &tail -> head
move.l #0,(A3) ; NULL -> tail
move.l A2,8(A2) ; &head -> tailpred
move.l sp,MN_REPLYPORT(A1)
move.l A1,A2 ; save message
jsr _LVOPutMsg(A6) ; send the message
move.l A2,A0
bsr _lWaitMsg ; wait for reply
add.w #MP_SIZE,sp
movem.l (sp)+,A2/A3/A6
rts
_lCheckMsg: moveq.l #0,D0
cmp.b #NT_MESSAGE,LN_TYPE(A0) ;NT_MESSAGE == not replied
beq .lcm1
move.l A0,D0
.lcm1 rts
_lCheckPort: moveq.l #0,D0
move.l MP_MSGLIST+LH_HEAD(A0),A0
tst.l (A0) ;list empty?
beq .lcp1
move.l A0,D0 ;no, return first element
.lcp1 rts
_lWaitMsg: ;A0 = message to wait for
movem.l A2/A3/A6,-(sp)
move.l A0,A2 ;A2 = message
move.l MN_REPLYPORT(A0),A3 ;A3 = replyport
move.l 4,A6 ;A6 = execbase
.wmloop cmp.b #NT_MESSAGE,LN_TYPE(A2) ;while msg not replied
bne .wm1
move.b MP_SIGBIT(A3),D1 ;Wait on port signal
moveq.l #0,D0
bset.l D1,D0
jsr _LVOWait(A6)
bra .wmloop
.wm1 jsr _LVODisable(A6) ;remove from port
move.l A2,A1 ;A1 = message (A2)
jsr _LVORemove(A6)
jsr _LVOEnable(A6)
move.l A2,D0 ;return message
movem.l (sp)+,A2/A3/A6
rts
;WILDCMP(wild:D0, name:D1)
;
; Handles * and ?
;
;result: D0, 0 = no match, 1 = match
;
;auto:
; D2 bi
; A2 wildcard string
; A3 name string
; A4 back-array (of size MAXB * 2 * 4)
MAXB EQU 8
_lWildCmp: movem.l D2/A2-A4,-(sp)
move.l D0,A2
move.l D1,A3
sub.l #MAXB*2*8,sp
move.l sp,A4
moveq.l #0,D2
.wcloop moveq.l #1,D0
move.b (A2),D1
bne .w1
tst.b (A3)
beq .wcdone
.w1 cmp.b #'*',D1
bne .w10
cmp.w #MAXB,D2
bne .w2
moveq.l #-1,D0 ; error
bra .wcdone
.w2 move.w D2,D0 ; back[bi][0] = w i.e. back+bi*8
asl.w #3,D0 ; back[bi][1] = n
move.l A2,(A4,D0.w)
move.l A3,4(A4,D0.w)
addq.w #1,D2
addq.l #1,A2
bra .wcloop
.wgoback subq.w #1,D2
bmi .w5
move.w D2,D0
asl.w #3,D0
move.l 4(A4,D0.w),A0
tst.b (A0)
beq .wgoback
.w5 tst.w D2
bmi .wcret0
move.w D2,D0
asl.w #3,D0
move.l (A4,D0.w),A2
addq.l #1,A2
add.l #1,4(A4,D0.w)
move.l 4(A4,D0.w),A3
addq.l #1,D2
bra .wcloop
.w10 cmp.b #'?',D1
bne .w20
tst.b (A3)
bne .wcbreak
tst.w D2
bne .wgoback
bra .wcret0
.w20 move.b (A3),D0
cmp.b #'A',D0
blo .w21
cmp.b #'Z',D0
bhi .w21
or.b #$20,D0
.w21 move.b (A2),D1
cmp.b #'A',D1
blo .w22
cmp.b #'Z',D1
bhi .w22
or.b #$20,D1
.w22 cmp.b D0,D1
beq .wcbreak
tst.w D2
bne .wgoback
bra .wcret0
.wcbreak tst.b (A2)+
bne .wcb1
subq.l #1,A2
.wcb1 tst.b (A3)+
bne .wcb2
subq.l #1,A3
.wcb2 bra .wcloop
.wcret0 moveq.l #0,D0
.wcdone add.l #MAXB*2*8,sp
movem.l (sp)+,D2/A2-A4
rts
; long var[2] = { 0, 0 };
;
; These routines provide fast exclusive
; locks. Up to 8 independant locks may be used for
; each 4 byte address.
;
; LockAddr(&var[0]:A0)
; LockAddrB(bit:D0, &var[0]:A0)
; UnLockAddr(&var[0]:A0)
; UnLockAddrB(bit:D0, &var[0]:A0)
_lLockAddr: moveq.l #0,D0 ; bit 0
_lLockAddrB: bset.b D0,4(A0) ; attempt to gain lock
bne .la10
rts ; was clear, so got it
.la10 movem.l A2/A6,-(sp) ; else failed,
move.l 4,A6 ; A6 = SYSBase
FORBID
bset.b D0,4(A0) ; try again
beq .la20 ; got it!
move.w D0,-(sp) ; bit# 12(sp)
move.l ThisTask(A6),-(sp) ; task# 8(sp)
move.l A0,-(sp) ; &var 4(sp)
move.l (A0),-(sp) ; Next (sp)
move.l sp,(A0) ; (put at head of list)
.la15 moveq.l #$10,D0 ; wait (semaphore signal)
jsr _LVOWait(A6)
move.w 12(sp),D0 ; try for lock
move.l 4(sp),A0
bset.b D0,4(A0)
bne .la15 ; loop until get it
.la16 cmp.l (A0),sp ; unlink, find our node!
beq .la18
move.l (A0),A0
bra .la16
.la18 move.l (sp),(A0)
add.w #14,sp
.la20
PERMIT
movem.l (sp)+,A2/A6
rts
_lUnLockAddr: moveq.l #0,D0 ; bit 0
_lUnLockAddrB: bclr.b D0,4(A0) ; clear lock bit
move.l (A0),D1 ; anybody waiting?
beq .ulrts ; no, rts
movem.l D2/A2/A6,-(sp) ; yes, wake 'm all up
move.b D0,D2 ; D2 = bit#
move.l 4,A6 ; A6 = SYSBase
FORBID
move.l (A0),D1 ; get pointer again after FORBID
beq .ul20 ; no, rts (close a window)
.ul10 move.l D1,A2 ; A2 = node
cmp.b 13(A2),D2 ; waiting on our bit #?
bne .ul18 ; no
move.l 8(A2),A1 ; yes, signal the node
moveq.l #$10,D0
jsr _LVOSignal(A6) ; signal EVERYONE waiting
.ul18 move.l (A2),D1 ; next
bne .ul10
.ul20
PERMIT
movem.l (sp)+,D2/A2/A6
.ulrts rts
; FindName2(list:D0, name:A0)
;
; Search the node list as in FindName(), but also ignore
; NULL ln_name entries, which FindName() does not do. This
; routine will also return NULL if given an uninitialized
; list header (completely zero'd). Finally, it will not
; bother to do a string compare if the two pointers are
; the same.
_lFindName2: movem.l A2/A3,-(sp)
move.l D0,A1
tst.l (A1) ; uninitialized list header
beq .fn2fail
.fn2loop move.l (A1),A1 ; get first/next node
tst.l (A1) ; end of list?
beq .fn2fail
move.l LN_NAME(A1),D0 ; name
beq .fn2loop ; NULL, skip
cmp.l D0,A0 ; pointers are the same!
beq .fn2succ ; don't bother w/cmp.
move.l D0,A2
move.l A0,A3
.fn2l2 cmpm.b (A2)+,(A3)+
bne .fn2loop
tst.b -1(A2)
bne .fn2l2
.fn2succ move.l A1,D0
movem.l (sp)+,A2/A3
rts
.fn2fail moveq.l #0,D0
movem.l (sp)+,A2/A3
rts
#endasm
\Rogue\Monster\
else
echo "will not over write src/misc.c"
fi
if [ `wc -c src/misc.c | awk '{printf $1}'` -ne 8171 ]
then
echo `wc -c src/misc.c | awk '{print "Got " $1 ", Expected " 8171}'`
fi
if `test ! -s src/newres.c`
then
echo "writing src/newres.c"
cat > src/newres.c << '\Rogue\Monster\'
/*
*FUNC= GetRes A0
*FUNC= FreeRes A0
*FUNC= FreeAllRes A0
*FUNC= ChownRes D0/D1/A0
*FUNC= UnLinkAllRes A0
*FUNC= ReLinkAllRes A0
*FUNC= SetResFlags D0/D1/A0
*FUNC= AddRes D0/D1/D2/A0
*FUNC= RemRes A0
*FUNC= GetResInfo D0/D1/A0
*FUNC= GetResList D0/D1/D2/A0
*FUNC= GetFileList D0/D1/D2/A0
*FUNC= AddPrivResFile D0/D1
*FUNC= RemPrivResFiles A0
*FUNC= AddGlobResFile D0/D1
*FUNC= RemGlobResFiles A0
*FUNC= AddResSwapDir D0/D1/A0
*FUNC= RemResSwapDirs A0
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*FUNC= NULL -
*
*/
#include <local/typedefs.h>
#include <local/res.h>
#include "file.h"
/*
* resptr = GetRes(resnametype) char *resnametype;
*
* (1) The resource is SHARED, is tagged with its name, then
* (a) if swapped, swap in
* (b) incr. ref. count.
* (2) The resource is not shared, re-load from disk
*
*/
GetRes(rnt)
register char *rnt;
{
RMSG RMsg;
register char *str;
for (str = rnt + strlen(rnt); str >= rnt && *str != '.'; --str);
RMsg.Arg1 = (long)rnt;
RMsg.Arg2 = (long)str + 1;
if ((RMsg.Arg3 = str - rnt) < 0)
RMsg.Arg3 = 0;
RMsg.Arg4 = strlen(str + 1);
DoSyncMsg(&ResPort, &RMsg);
return(RMsg.Res1);
}
resptr= GetRes(resnametype) char *resnametype;
This function retrieves the requested resource, doing any
translations required to get the resource into the requested
type. NULL is returned if the resource could not be found
or could not be translated to the requested type.
In-Memory private resources are searched first, then the private
resource files for the task, then In-Memory system resources, then
the global resource files for the system. Openning an already-open
resource causes one of two actions depending on whether the resource
is shared or not. If shared, the reference count is simply
incremented, otherwise a private copy of the resource is made.
Example: Win = GetRes("Charlie.Window");
error = FreeRes(resptr)
Free a resource that you retrieved via GetRes(). Only the task
that owns the resource may free it (though several tasks may own
a resource through duplication and ownership changes). 1 is
returned on success, 0 on error.
numres= FreeAllRes(task)
Free all resources associated with the specified task (NULL for
self).
error = ChownRes(resptr, fromtask, totask)
Change ownership of a resource from the source task to the
destination task. The resource must be owned by the source
task or an error will occur (0 return value). 1 is returned
on success. NULL may be specified for either or both tasks
meaning the calling task.
handle= UnLinkAllRes(task)
Unlink all resources associated with the specified task (NULL
for self) and return a handle representing those resources.
This is useful for shells and such to keep their resources from
getting removed by commands they run. Combined with the NUNLINK
flag one can pass resources to a Command and keep the rest out of
reach.
(void) ReLinkAllRes(handle, task)
Link all the resources represented by the handle to the specified
task (NULL for self).
oldfl = SetResFlags(resptr, newflags, flagsmask)
Modify the flags associated with a resource. NOTE: If multiple
references to a shared resource exist, all are modified. Some
modifications may be disallowed by the system. This call is
normally used to modify the LOCKED and SWAPABLE flags (note that
the SWAPABLE flag can be changed back and forth only for resource
which support it).
error = AddRes(resnametype, flags, ptr, ctlcode);
char *resnametype;
long flags;
APTR ptr;
long (*ctlcode)();
Add a resource to the system. The resource is placed either in
the task's privately accessable in-memory resource list or
in the system global accessable in-memory resource list depending
on the specified flags. One may now GetRes() the resource.
ONLY VIRTUAL RESOURCES MAY BE ADDED IN THIS WAY. The VIRTUAL
and LOCKED flags are automatically set.
If flags specifies a VIRTUAL resource
error = RemRes(resname)
Remove the specified resource. An error will occur and the resource
will not be removed (1) if it does not exist in memory, or (2) it
is currently being referenced. (Note: the resource is removed even
if it is swapped or locked).
error = GetResInfo(resname, &flags, &bytes)
Get information on a resource. Information may not exist for a
resource if it is not currently in memory and would have to be
translated to get to the right type.
error = GetResList(wildcard, from, &av, &ac);
from: mask, bit 0 search private list
1 search system list
2 <not used>
3 search in-memory private list
4 search in-memory global list
Return an ARGC/ARGV list of resource names. Note that some names
might be duplicated if searching multiple lists. Restricting the
search to in-memory lists give resources which are already in
memory (but might be swapped out or removed at any time for those
with no references)
RESOURCE FILES
error = GetFileList(wildcard, from, &av, &ac);
from: mask, bit 0 search private list
1 search system list
2 search swap list
Return an ARGC/ARGV list of the files which match the specified
wildcard from the private list, system list, or system swap dir
list (in which case you get directory names). This list has been
allocated, and can be freed as follows:
Loop through all entries for (i = 0; i < ac; ++i)
FreeMem(av[i], strlen(av[i])+1);
Free the array itself: FreeMem(av, sizeof(char *) * (ac+1));
num = AddPrivResFile(filename, pri)
Add a file name to the list of resource files for this task. These
are scanned before global files when a resource is requested. All
files in the list are write protected (i.e. a shared lock is kept
for each file). Thus, such files cannot be updated until removed
from the list.
Can also be used to modify the priority of an existing file
num = RemPrivResFiles(wildcard)
Remove zero or more file names from the list of resource files for
this task. A wildcard pattern (* and ?) is accepted.
Note for command processors: commands you run might execute
this command for *.
num = AddGlobResFile(filename, pri)
Same as AddPrivResFile() but applies to the system list, which is
searched last and by any requesting task. Wildcard file names are
NOT accepted. The file need not exist at this time, and references
to unmounted volumes are allowed.
Can also be used to modify the priority of an existing entry
num = RemGlobResFiles(wildcard)
Remove zero or more resource files from the global list. Again,
a wildcard filename is accepted.
num = AddResSwapDir(dirname, pri, maxkbytes) char *dirname;
char pri;
long maxkbytes
Add a directory to the list of directories the resource system
can swap to. The maximum number of KBytes of material allowed
in the directory should be specified. You can also use this
call to modify the priority and maxkbytes for an entry.
The highest priority directories are used before lower priority
directories. Not all directories need be mounted, but if a swapin
occurs from an unmounted directory a requester will appear.
A lock is kept on each specified directory.
num = RemResSwapDirs(wildcard)
Remove directories associated with the resource swap areas.
\Rogue\Monster\
else
echo "will not over write src/newres.c"
fi
if [ `wc -c src/newres.c | awk '{printf $1}'` -ne 7611 ]
then
echo `wc -c src/newres.c | awk '{print "Got " $1 ", Expected " 7611}'`
fi
if `test ! -s src/mem.asm`
then
echo "writing src/mem.asm"
cat > src/mem.asm << '\Rogue\Monster\'
; MEM.ASM
public _lBZero ; Zero a block of memory
public _lBSet ; Set a block of memory to (byte val)
public _lBMov ; move a block of memory
public _lBCmp ; compare two blocks of memory
; BSET(buffer:D0, len:D1, byte:A0.B)
; BZERO(buffer:D0, len:D1)
_lBZero: move.w #0,A0
_lBSet: exg A0,D0 ; A0 = buffer (D0=byte)
exg D0,D1 ; D0 = length (D1=byte)
add.l D0,A0 ; start at end of address
cmp.l #40,D0 ; unscientifically chosen
bls .bs2
bra .bs10
.bs1 move.b D1,-(A0) ; any count < 65536
.bs2 dbf D0,.bs1
rts
; at least 2 bytes in count (D0)
.bs10 movem.l D2-D7/A2-A6,-(sp) ;ant count > 4
move.l A0,D2
btst.l #0,D2 ; is it aligned?
beq .bs22
move.b D1,-(A0) ; no, copy one byte
subq.l #1,D0
.bs22 andi.l #$FF,D1 ; expand data D1.B -> D2-D7/A1-A6
move.l D1,D2 ; D1 000000xx D2 000000xx
asl.w #8,D2 ; 0000xx00
or.w D2,D1 ; 0000xxxx
move.w D1,D2 ; 0000xxxx 0000xxxx
swap D2 ; 0000xxxx xxxx0000
or.l D1,D2 ; D2.L
move.l D2,D3
move.l D2,D4
move.l D2,D5
move.l D2,D6
move.l D2,D7
move.l D2,A1
move.l D2,A2
move.l D2,A3
move.l D2,A4
move.l D2,A5
move.l D2,A6 ; D2-D7/A1-A6 (12 registers)
move.l #12*4,D1 ; bytes per transfer (48)
.bs30 sub.l D1,D0 ; pre subtract
bmi .bs40
.bs31 movem.l D2-D7/A1-A6,-(A0)
sub.l D1,D0
bpl .bs31
.bs40 add.w D1,D0 ; less than 48 bytes remaining
move.w #4,D1 ; by 4's
sub.w D1,D0
bmi .bs50
.bs41 move.l D2,-(A0)
sub.w D1,D0
bpl .bs41
.bs50 add.w D1,D0
bra .bs52
.bs51 move.b D2,-(A0) ; by 1's
.bs52 dbf D0,.bs51
movem.l (sp)+,D2-D7/A2-A6
rts
; BCMP(src:D0, dst:D1, len:A0)
_lBCmp: exg A0,D0 ;A0 = src, D0 = len
exg A1,D1 ;A1 = dst
tst.l D0
beq .bcsucc
cmp.w D0,D0 ;force Z bit
bra .bc2
.bc1 cmpm.b (A0)+,(A1)+
.bc2 dbne D0,.bc1
bne .bcfail
sub.l #$10000,D0
bcc .bc1
.bcsucc moveq.l #1,D0 ;success!
rts
.bcfail moveq.l #0,D0 ;failure!
rts
; BMOV(src:D0, dst:D1, len:A0)
;
; The memory move algorithm is somewhat more of a mess
; since we must do it either ascending or decending.
_lBMov: exg A0,D0 ;A0 = src, D0 = len
exg A1,D1 ;A1 = dst
cmp.l A0,A1
beq .bmend
bls .bmup
.bmdown adda.l D0,A0 ;descending copy
adda.l D0,A1
move.w A0,D1 ;CHECK WORD ALIGNED
btst.l #0,D1
bne .bmdown1
move.w A1,D1
btst.l #0,D1
bne .bmdown1
cmp.l #259,D0 ;chosen by calculation.
blo .bmdown8
move.l D0,D1 ;overhead for bmd44: ~360
divu #44,D1
bvs .bmdown8 ;too big (> 2,883,540)
movem.l D2-D7/A2-A6,-(sp) ;use D2-D7/A2-A6 (11 regs)
move.l #11*4,D0
bra .bmd44b
.bmd44a sub.l D0,A0 ;8 total 214/44bytes
movem.l (A0),D2-D7/A2-A6 ;12 + 8*11 4.86 cycles/byte
movem.l D2-D7/A2-A6,-(A1) ; 8 + 8*11
.bmd44b dbf D1,.bmd44a ;10
swap D1 ;D0<15:7> already contain 0
move.w D1,D0 ;D0 = remainder
movem.l (sp)+,D2-D7/A2-A6
.bmdown8 move.w D0,D1 ;D1<2:0> = #bytes left later
lsr.l #3,D0 ;divide by 8
bra .bmd8b
.bmd8a move.l -(A0),-(A1) ;20 total 50/8bytes
move.l -(A0),-(A1) ;20 = 6.25 cycles/byte
.bmd8b dbf D0,.bmd8a ;10
sub.l #$10000,D0
bcc .bmd8a
move.w D1,D0 ;D0 = 0 to 7 bytes
and.l #7,D0
bne .bmdown1
rts
.bmd1a move.b -(A0),-(A1) ;12 total 22/byte
.bmdown1 ; = 22 cycles/byte
.bmd1b dbf D0,.bmd1a ;10
sub.l #$10000,D0
bcc .bmd1a
rts
.bmup move.w A0,D1 ;CHECK WORD ALIGNED
btst.l #0,D1
bne .bmup1
move.w A1,D1
btst.l #0,D1
bne .bmup1
cmp.l #259,D0 ;chosen by calculation
blo .bmup8
move.l D0,D1 ;overhead for bmu44: ~360
divu #44,D1
bvs .bmup8 ;too big (> 2,883,540)
movem.l D2-D7/A2-A6,-(sp) ;use D2-D7/A2-A6 (11 regs)
move.l #11*4,D0
bra .bmu44b
.bmu44a movem.l (A0)+,D2-D7/A2-A6 ;12 + 8*11 ttl 214/44bytes
movem.l D2-D7/A2-A6,(A1) ;8 + 8*11 4.86 cycles/byte
add.l D0,A1 ;8
.bmu44b dbf D1,.bmu44a ;10
swap D1 ;D0<15:7> already contain 0
move.w D1,D0 ;D0 = remainder
movem.l (sp)+,D2-D7/A2-A6
.bmup8 move.w D0,D1 ;D1<2:0> = #bytes left later
lsr.l #3,D0 ;divide by 8
bra .bmu8b
.bmu8a move.l (A0)+,(A1)+ ;20 total 50/8bytes
move.l (A0)+,(A1)+ ;20 = 6.25 cycles/byte
.bmu8b dbf D0,.bmu8a ;10
sub.l #$10000,D0
bcc .bmu8a
move.w D1,D0 ;D0 = 0 to 7 bytes
and.l #7,D0
bne .bmup1
rts
.bmu1a move.b (A0)+,(A1)+
.bmup1
.bmu1b dbf D0,.bmu1a
sub.l #$10000,D0
bcc .bmu1a
.bmend rts
\Rogue\Monster\
else
echo "will not over write src/mem.asm"
fi
if [ `wc -c src/mem.asm | awk '{printf $1}'` -ne 4649 ]
then
echo `wc -c src/mem.asm | awk '{print "Got " $1 ", Expected " 4649}'`
fi
if `test ! -d util`
then
mkdir util
echo "mkdir util"
fi
if `test ! -s util/gtd.c`
then
echo "writing util/gtd.c"
cat > util/gtd.c << '\Rogue\Monster\'
/*
* GTD -GetTaskData/FreeTaskData tester
*
* Matthew Dillon, 30 Sep 1988
*
* gtd - show task memlist entries
* gtd <name> - remove an entry
* gtd <name> <bytes> - add/retrieve an entry, display it, then
* store sequential values into the buffer.
*/
#include <stdio.h>
#include <local/typedefs.h>
#include <local/xmisc.h>
extern int Enable_Abort;
extern char *GetTaskData();
main(ac,av)
char *av[];
{
char *ptr;
long bytes;
short i;
TASK *task = FindTask(NULL);
Enable_Abort = 0;
if (openlibs(DRES_LIB) == 0)
exit(1);
if (ac == 1) {
MEMLIST *ml;
for (ml = GetHead(&task->tc_MemEntry); ml; ml = GetSucc(ml)) {
printf("memlist %08lx %ld %s\n", ml, ml->ml_NumEntries,
((ml->ml_Node.ln_Name) ? ml->ml_Node.ln_Name : "NULL")
);
}
goto fail;
}
bytes = atoi(av[2]);
printf("%s,%ld :", av[1], bytes);
fflush(stdout);
if (ac == 2) {
printf("result %ld\n", FreeTaskData(av[1]));
} else {
ptr = GetTaskData(av[1], bytes);
if (!ptr) {
puts("failed");
goto fail;
}
printf("%08lx ", ptr);
fflush(stdout);
for (i = 0; i < bytes; ++i) {
printf("%02x ", ptr[i]);
ptr[i] = i;
}
}
fail:
closelibs(-1);
}
\Rogue\Monster\
else
echo "will not over write util/gtd.c"
fi
if [ `wc -c util/gtd.c | awk '{printf $1}'` -ne 1238 ]
then
echo `wc -c util/gtd.c | awk '{print "Got " $1 ", Expected " 1238}'`
fi
if `test ! -s util/testipc.c`
then
echo "writing util/testipc.c"
cat > util/testipc.c << '\Rogue\Monster\'
/*
* TESTIPC <appname> <file> <file> <file> ... <inputfile
*
* input file format:
*
* appname delay file text
*
*/
#include <local/typedefs.h>
#include <local/ipc.h>
#include <local/xmisc.h>
#include <stdio.h>
extern int Enable_Abort;
extern PORT *OpenIPC();
char **Av;
short Ac;
main(ac, av)
char *av[];
{
PORT *port;
Av = av;
Ac = ac;
if (ac == 1) {
puts("TESTIPC <appname> <subname> ... <subname> <inputfile");
puts("input file format:");
puts("<appname> <delay-1/50ths> <subname> <text>");
exit(1);
}
Enable_Abort = 0;
if (openlibs(DRES_LIB) <= 0) {
puts("Unable to open dres.library");
exit(1);
}
port = OpenIPC(av[1], 0);
if (port == NULL) {
puts("unable to open port");
closelibs(-1);
exit(1);
}
printf("port: %08lx\n", port);
{
char apname[32];
long delay;
char subname[32];
char text[64];
char tbuf[128];
IPCMSG msg;
extern void handler();
BZero(&msg, sizeof(msg));
msg.Msg.mn_ReplyPort = CreatePort(NULL, 0);
puts("scanf");
while (scanf("%s %ld %s %s", apname, &delay, subname, text) == 4) {
printf("DO(%s %ld %s %s) ", apname, delay, subname, text);
fflush(stdout);
strcpy(tbuf, subname);
strcpy(tbuf+strlen(subname)+1, text);
msg.TBuf = (APTR)tbuf;
msg.TLen = strlen(subname)+strlen(text)+2;
DoIPC2(apname, &msg, handler, port);
if (msg.RFlags & IF_NOTFND) {
if (msg.RFlags & IF_NOAPP)
puts("Application not found");
else
puts("subname not found");
} else {
if (msg.RFlags & IF_ERROR)
printf("Error: %s\n", msg.RBuf);
else
printf("OK: %s\n", msg.RBuf);
}
FreeIPC(&msg);
if (delay)
Delay(delay);
if (CheckPort(port))
handler(port);
}
DeletePort(msg.Msg.mn_ReplyPort);
}
CloseIPC(port);
closelibs(-1);
}
void
handler(port)
PORT *port;
{
IPCMSG *msg;
short i, j;
while (msg = GetMsg(port)) {
register char *ptr = (char *)msg->TBuf;
printf("Received IPC command: %s ", ptr);
for (j = 0; ptr[j] && ptr[j] != ' '; ++j);
for (i = 2; i < Ac; ++i) {
if (strlen(Av[i]) == j && strncmp(Av[i], ptr, j) == 0)
break;
}
if (i < Ac) {
puts("MATCH");
ReplyIPC(msg, "GotIt!", 7, 0);
} else {
puts("PASSED");
ReplyIPC(msg, "Failed", 7, IF_NOTFND);
}
}
}
\Rogue\Monster\
else
echo "will not over write util/testipc.c"
fi
if [ `wc -c util/testipc.c | awk '{printf $1}'` -ne 2309 ]
then
echo `wc -c util/testipc.c | awk '{print "Got " $1 ", Expected " 2309}'`
fi
if `test ! -s util/test.c`
then
echo "writing util/test.c"
cat > util/test.c << '\Rogue\Monster\'
/*
* TEST.C
*
* Test Library Functions.
*/
#include <typedefs.h>
#include <stdio.h>
typedef struct Library LIB;
LIST ListA;
LIST ListB;
NODE Node1;
NODE Node2;
NODE Node3;
short Glob;
extern int Enable_Abort;
LIB *DMiscSupportBase;
extern LIB *OpenLibrary();
extern char *AllocMem();
extern char *GetHead();
extern char *GetTail();
extern char *GetSucc();
extern char *GetPred();
extern char *GetHeadOff();
extern char *GetTailOff();
extern char *GetSuccOff();
extern char *GetPredOff();
extern long srch();
main()
{
Enable_Abort = 0;
DMiscSupportBase = OpenLibrary("dmiscsup.library", 0);
if (!DMiscSupportBase) {
puts("Unable to open library");
exit(1);
}
printf("library at: %08lx\n", DMiscSupportBase);
printf("library flags: %02lx Rev: %ld OpenCnt: %ld\n",
DMiscSupportBase->lib_Flags,
DMiscSupportBase->lib_Revision,
DMiscSupportBase->lib_OpenCnt
);
NewList(&ListA);
NewList(&ListB);
AddTail(&ListA, &Node1);
AddTail(&ListA, &Node2);
AddTail(&ListA, &Node3);
printf("\nGetHead() "); fflush(stdout);
results((NODE *)GetHead(&ListA) == &Node1);
results(GetHead(&ListB) == NULL);
printf("\nGetTail() "); fflush(stdout);
results((NODE *)GetTail(&ListA) == &Node3);
results(GetTail(&ListB) == NULL);
printf("\nGetSucc() "); fflush(stdout);
results((NODE *)GetSucc(&Node1) == &Node2);
results((NODE *)GetSucc(&Node3) == NULL);
printf("\nGetPred() "); fflush(stdout);
results((NODE *)GetPred(&Node3) == &Node2);
results((NODE *)GetPred(&Node1) == NULL);
printf("\nGetHeadOff() "); fflush(stdout);
results(GetHeadOff(&ListA, 3) == (char *)&Node1 - 3);
results(GetHeadOff(&ListB, 3) == NULL);
printf("\nGetTailOff() "); fflush(stdout);
results(GetTailOff(&ListA, 3) == (char *)&Node3 - 3);
results(GetTailOff(&ListB, 3) == NULL);
printf("\nGetSuccOff() "); fflush(stdout);
results(GetSuccOff((char *)&Node1 - 3, 3) == (char *)&Node2 - 3);
results(GetSuccOff((char *)&Node3 - 3, 3) == NULL);
printf("\nGetPredOff() "); fflush(stdout);
results(GetPredOff((char *)&Node2 - 3, 3) == (char *)&Node1 - 3);
results(GetPredOff((char *)&Node1 - 3, 3) == NULL);
printf("\nSearchFwdNode() "); fflush(stdout);
Glob = 0; SearchFwdNodeOff(NULL, srch, 3, 27); results(Glob == 0);
Glob = 0; SearchFwdNodeOff(GetHeadOff(&ListA, 3), srch, 3, 27); results(Glob == 3);
printf("\nSearchRvsNode() "); fflush(stdout);
Glob = 0; SearchRvsNodeOff(NULL, srch, 3, 27); results(Glob == 0);
Glob = 0; SearchRvsNodeOff(GetTailOff(&ListA, 3), srch, 3, 27); results(Glob == 3);
puts("");
wildtest();
memory_test();
RemLibrary(DMiscSupportBase);
CloseLibrary(DMiscSupportBase);
}
results(bool)
{
if (bool)
printf(" ok");
else
printf(" fail");
fflush(stdout);
}
srch(sptr, arg)
{
++Glob;
printf(".");
fflush(stdout);
if (arg != 27) /* failure */
return(1);
return(NULL);
}
/*
* TEST: WildCmp()
*/
wildtest()
{
printf("WildCmp() "); fflush(stdout);
results(WildCmp("a??b", "axeb") == 1);
results(WildCmp("a??b", "axebx")== 0);
results(WildCmp("*/x*y*b", "a/x/u/xcharliey/b") == 1);
results(WildCmp("*/x*y*b", "a/x/u/xcharlieq/b") == 0);
puts("");
}
/*
* TEST: BZero(), BSet(), BMov(), and BCmp();
*/
memory_test()
{
long Size = 80000; /* MUST BE 80000 */
short result;
short i;
char *ary1 = AllocMem(Size, MEMF_PUBLIC);
char *ary2 = AllocMem(Size, MEMF_PUBLIC);
printf("\nTEST MEMORY SUBROUTINES:\n");
if (!ary1 || !ary2) {
puts(" UNABLE TO ALLOCATE TWO CONTIGUOUS 80K SEGMENTS");
puts(" THUS, CANNOT PERFORM MEMORY ROUTINES TEST.");
goto fail;
}
/*
* Test BZero/BSet (both are the same subroutine, essentially).
* Test: >64K, odd start, odd length.
*/
printf(" BZero(): "); fflush(stdout);
xbset(ary1, Size, 43);
xbset(ary2, Size, 43);
printf("."); fflush(stdout);
BZero(ary1 + 1000, 20);
BZero(ary1 + 1200, 70000);
BZero(ary2 + 512 + 3, 70000);
printf("."); fflush(stdout);
results(xbcheck(ary1, 1000, 43));
results(xbcheck(ary1 + 1000, 20, 0));
results(xbcheck(ary1 + 1020, 1200 - 1020, 43));
results(xbcheck(ary1 + 1200, 70000, 0));
results(xbcheck(ary1 + 1200 + 70000, Size - 1200 - 70000, 43));
printf("\n BSet(): "); fflush(stdout);
xbset(ary1, Size, 43);
xbset(ary2, Size, 43);
printf("."); fflush(stdout);
BSet(ary1 + 999, 21, 5);
BSet(ary1 + 1201, 70001, 6);
BSet(ary2 + 512 + 1, 69999, 7);
printf("."); fflush(stdout);
results(xbcheck(ary1, 999, 43));
results(xbcheck(ary1 + 999, 21, 5));
results(xbcheck(ary1 + 999 + 21, 1201 - 999 - 21, 43));
results(xbcheck(ary1 + 1201, 70001, 6));
results(xbcheck(ary1 + 1201 + 70001, Size - 1201 - 70001, 43));
results(xbcheck(ary2, 512 + 1, 43));
results(xbcheck(ary2 + 512 + 1, 69999, 7));
results(xbcheck(ary2 + 512 + 1 + 69999, Size - 69999 - 512 - 1, 43));
/*
* TEST BMov(). Odd start, overlapping blocks in forward and
* reverse.
*/
printf("\n BMov(): 1"); fflush(stdout);
xbset(ary1, Size, 43);
xbset(ary2, Size, 43);
xbiset(ary1 + 1001, 69999, 1);
xbiset(ary2 + 1003, 70001, 1);
BMov(ary1 + 1001, ary1 + 997, 69999);
BMov(ary2 + 1003, ary2 + 1008, 70001);
results(xbicheck(ary1 + 997, 69999, 1));
results(xbicheck(ary2 + 1008, 70001, 1));
results(xbcheck(ary1, 997, 43));
results(xbcheck(ary1 + 1001 + 69999, Size - 1001 - 69999, 43));
results(xbcheck(ary2, 1003, 43));
results(xbcheck(ary2 + 1008 + 70001, Size - 1008 - 70001, 43));
printf("\n BMov(): 2"); fflush(stdout);
xbset(ary1, Size, 43);
xbset(ary2, Size, 43);
xbiset(ary1 + 1024, 70000, 1);
xbiset(ary2 + 1024, 70000, 1);
BMov(ary1 + 1024, ary1 + 1004, 70000);
BMov(ary2 + 1024, ary2 + 1044, 70000);
results(xbicheck(ary1 + 1004, 70000, 1));
results(xbicheck(ary2 + 1044, 70000, 1));
results(xbcheck(ary1, 1004, 43));
results(xbcheck(ary1 + 1024 + 70000, Size - 70000 - 1024, 43));
results(xbcheck(ary2, 1024, 43));
results(xbcheck(ary1 + 1044 + 70000, Size - 70000 - 1044, 43));
puts("");
printf(" SPEEDTEST (K/sec BMov lw bndry, fastmem): %ld K/sec\n", speedtest(MEMF_FAST, 0, 0));
printf(" SPEEDTEST (K/sec BSet lw bndry, fastmem): %ld K/sec\n", speedtest(MEMF_FAST, 1, 0));
printf(" SPEEDTEST (K/sec BMov lw bndry, chipmem): %ld K/sec\n", speedtest(MEMF_CHIP, 0, 0));
printf(" SPEEDTEST (K/sec BSet lw bndry, chipmem): %ld K/sec\n", speedtest(MEMF_CHIP, 1, 0));
puts("");
printf(" SPEEDTEST (K/sec BMov by bndry, fastmem): %ld K/sec\n", speedtest(MEMF_FAST, 0, 1));
printf(" SPEEDTEST (K/sec BMov by bndry, chipmem): %ld K/sec\n", speedtest(MEMF_CHIP, 0, 1));
fail:
if (ary1)
FreeMem(ary1, Size);
if (ary2)
FreeMem(ary2, Size);
}
speedtest(memtype, zero, off)
{
char *buf = AllocMem(65536+256, memtype);
short i;
long s;
if (!buf)
return(0);
s = ltm();
for (i = 0; i < 128; ++i) {
if (zero)
BSet(buf + off, 65536, 1);
else
BMov(buf + off, buf + 128 + off, 65536);
}
s = ltm() - s; /* 1/50ths second for 64K * 128 */
FreeMem(buf, 65536+256);
return(64 * 128 * 50 / s);
}
ltm()
{
long st[3];
DateStamp(st);
return(st[2] + 50 * 60 * st[1] + 50 * 60 * 60 * 24 * st[0]);
}
xbset(s, n, v)
register char *s;
register long n;
register char v;
{
while (n--)
*s++ = v;
}
xbiset(s, n, v)
register char *s;
register long n;
register char v;
{
while (n--) {
++v;
*s++ = v;
}
}
xbcheck(s, n, v)
register char *s;
register long n;
register char v;
{
char *orig = s;
short errs = 255;
while (n--) {
if (*s++ != v) {
if (errs) {
--errs;
printf("(%ld)", s - orig - 1);
} else {
printf("giveup");
return(0);
}
}
}
return(errs == 255);
}
xbicheck(s, n, v)
register char *s;
register long n;
register char v;
{
char *orig = s;
short errs = 255;
while (n--) {
++v;
if (*s++ != v) {
if (errs) {
--errs;
printf("(%ld)", s - orig);
} else {
printf("giveup");
return(0);
}
}
}
return(errs == 255);
}
\Rogue\Monster\
else
echo "will not over write util/test.c"
fi
if [ `wc -c util/test.c | awk '{printf $1}'` -ne 8363 ]
then
echo `wc -c util/test.c | awk '{print "Got " $1 ", Expected " 8363}'`
fi
if `test ! -s util/qtest.c`
then
echo "writing util/qtest.c"
cat > util/qtest.c << '\Rogue\Monster\'
/*
* QTEST.C
*/
#include <typedefs.h>
#include <stdio.h>
typedef struct Library LIB;
LIB *DMiscSupportBase;
long QHan;
long Count;
long EnErr;
long Error;
extern LIB *OpenLibrary();
extern TASK *FindTask();
handler(arg)
{
printf("ARG: %ld ************\n", arg);
}
main()
{
int i;
DMiscSupportBase = OpenLibrary("dmiscsup.library", 0);
if (!DMiscSupportBase) {
puts("Unable to open library");
exit(1);
}
puts("Q-TEST");
QHan = OpenQInts();
if (!QHan) {
puts("Unable to alloc. q ints");
CloseLibrary(DMiscSupportBase);
exit(1);
}
printf("QHAn= %08lx\n", QHan);
puts("UnSetting NULL vector");
SetQVector(QHan, NULL, SIGBREAKB_CTRL_E, 0, 0);
puts("Setting ^D vector");
SetQVector(QHan, handler, SIGBREAKB_CTRL_D, 30, -20);
puts("UnSetting NULL vector");
SetQVector(QHan, NULL, SIGBREAKB_CTRL_E, 0, 0);
puts("Loop");
for (i = 0; i < 100; ++i) {
char oldpri = SetQPri(QHan, 127);
EnErr = 1;
printf("%ld cnt = %ld error = %ld (old=%ld) %08lx %08lx\n", i, Count, Error, oldpri,
SetSignal(0,0), FindTask(NULL)->tc_SigExcept
);
EnErr = 0;
SetQPri(QHan, oldpri);
}
puts("UnSetting NULL vector");
SetQVector(QHan, NULL, SIGBREAKB_CTRL_E, 0, 0);
printf("%ld cnt = %ld error = %ld\n", i, Count, Error);
puts("closing");
CloseQInts(QHan);
puts("closelib");
RemLibrary(DMiscSupportBase);
CloseLibrary(DMiscSupportBase);
}
\Rogue\Monster\
else
echo "will not over write util/qtest.c"
fi
if [ `wc -c util/qtest.c | awk '{printf $1}'` -ne 1448 ]
then
echo `wc -c util/qtest.c | awk '{print "Got " $1 ", Expected " 1448}'`
fi
if `test ! -s util/testarg.c`
then
echo "writing util/testarg.c"
cat > util/testarg.c << '\Rogue\Monster\'
/*
*
*
*/
#include <local/xmisc.h>
extern int Enable_Abort;
char *
getv(name)
char *name;
{
printf("GET: '%s'\n", name);
return("VAR");
}
freev(str)
char *str;
{
printf("FREE: %s\n", str);
}
main(ac,av)
char *av[];
{
char buf[256];
char **Av;
short Ac;
long error;
Enable_Abort = 0;
openlibs(DRES_LIB);
while (gets(buf)) {
printf("Cmd: %s\n", buf);
Ac = ParseCmd(buf, &Av, getv, freev, &error, NULL);
printf("%08lx %ld\n", Av, Ac);
if (error) {
printf("ERROR!: %08lx\n", error);
}
if (Av) {
short i;
for (i = 0; i < Ac; ++i)
printf("%2ld: (%ld) \"%s\"\n", i, Av[i][-1], Av[i]);
puts("free");
FreeParseCmd(Av);
puts("ok");
}
}
closelibs(-1);
}
\Rogue\Monster\
else
echo "will not over write util/testarg.c"
fi
if [ `wc -c util/testarg.c | awk '{printf $1}'` -ne 743 ]
then
echo `wc -c util/testarg.c | awk '{print "Got " $1 ", Expected " 743}'`
fi
if `test ! -s util/x.c`
then
echo "writing util/x.c"
cat > util/x.c << '\Rogue\Monster\'
long Base;
main(ac,av)
char *av[];
{
int ver = atoi(av[1]);
Base = OpenLibrary("dres.library", ver);
if (Base) {
CloseLibrary(Base);
puts("openned ok");
} else {
puts("open failed");
}
}
\Rogue\Monster\
else
echo "will not over write util/x.c"
fi
if [ `wc -c util/x.c | awk '{printf $1}'` -ne 215 ]
then
echo `wc -c util/x.c | awk '{print "Got " $1 ", Expected " 215}'`
fi
echo "Finished archive 1 of 3"
# if you want to concatenate archives, remove anything after this line
exit
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.